package homework2

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"sync"
	"time"
)

type Set struct {
	value   map[string]string
	rwMutex sync.RWMutex
}

// 把value转成hashkey,也行还有其他更好的方法
func hashkey(text string) string {
	hash := md5.Sum([]byte(text))
	return hex.EncodeToString(hash[:])
}

// 初始化新set
func NewSet(args ...string) *Set {

	var newSet = make(map[string]string, len(args))
	for _, v := range args {
		newSet[hashkey(v)] = v
	}

	return &Set{
		value: newSet,
	}
}

// 查看是否存在
func (s *Set) JudgeElement(v string) bool {
	s.rwMutex.RLock()
	defer s.rwMutex.RUnlock()
	if _, ok := s.value[hashkey(v)]; !ok {
		return false
	}
	return true
}

// 添加
func (s *Set) Add(value string) {

	s.rwMutex.Lock()
	defer s.rwMutex.Unlock()
	s.value[hashkey(value)] = value

}

func (s *Set) Del(key string) {
	s.rwMutex.Lock()
	defer s.rwMutex.Unlock()
	delete(s.value, key)

}

func (s *Set) Merge(MergedSet *Set) {

	for _, v := range MergedSet.value {
		s.Add(v)
	}
}

func (s *Set) PrintElement() {
	s.rwMutex.RLock()
	for _, v := range s.value {
		fmt.Printf("%s,", v)
	}
	s.rwMutex.RUnlock()
	fmt.Printf("\n")
}

func main() {
	// 测试是否能去重
	s1 := NewSet("ji", "dq", "juan", "juan")
	// 测试set 合并
	s2 := NewSet("ji", "cdf", "cddf", "chuanjuan")

	s1.Merge(s2)
	s1.PrintElement()

	// 检查输入的string是否存在于set中
	fmt.Printf("是否存在set中 == %v\n", s1.JudgeElement("ji"))
	fmt.Printf("是否存在set中 == %v\n", s1.JudgeElement("qiang"))

	// 批量添加数据
	go func() {
		for i := 0; i < 1000000; i++ {
			s1.Add(fmt.Sprintf("num_%d", i))
		}
	}()

	// 删除数据
	go func() {
		for i := 0; i < 1000000; i++ {
			s1.Del(fmt.Sprintf("num_%d", i))
		}
	}()

	go func() {
		for i := 0; i < 100000; i++ {
			s1.Add(fmt.Sprintf("num_%d", i))
		}
	}()
	s1.PrintElement()
	time.Sleep(6 * time.Second)
	s1.PrintElement()
}

// 初始化时，考虑使用Add方法，删除 添加可以直接再对应的方法考虑添加多个